A high-interaction HTTP honeypot written in Go. It simulates 90+ real attack surfaces, tarpits every request with a cryptographically random delay, embeds honeytokens in fake responses to detect credential reuse, and automatically reports attackers to AbuseIPDB.
π Full documentation: https://andreaskasper.github.io/http-honeypot/
- π£ 90+ attack traps β Spring Actuator, WordPress, Exchange/OWA, SharePoint, ColdFusion, Citrix NetScaler, PAN-OS GlobalProtect, Fortinet, Kemp LoadMaster, VMware vCenter, Kubernetes, Docker API, AWS/GCP metadata, Git leaks, phpMyAdmin, Jenkins, Confluence, Metabase, Langflow, MCP/AI-agent recon, N-able N-central, developer credential stores, web shells, and more
- π― Honeytokens β IP-specific fake API keys (
hp_live_*) embedded in responses; detected and flagged with ahoneytoken_usedwebhook event when an attacker reuses them - π Dynamic response webhook β Return custom content for unknown URLs via
WEBHOOK_NEW_URLwith caching - π« AbuseIPDB integration β automatically reports attacking IPs with configurable per-IP cooldown
- π’ Tar-pit β
crypto/randdelay per request; prevents timing fingerprinting - π·οΈ
attack_tagβ every matched trap produces a machine-readable tag for webhook routing - π Log4Shell detection β scans all request headers and query strings for
${jndi:payloads - π API key capture β captures
X-Api-Key,Authorization: Bearer,Authorization: Token - π Structured JSON logging β one JSON line per request; built-in size-based log rotation
- π
LOG_DISABLEDβ disable all file logging while keeping notifications active - π Pushover β country-based mobile push; throttled to once per hour
- π Webhook β POST JSON to any URL on every attack event with optional per-IP rate limiting
- π Prometheus
/metricsβ HTTP Basic Auth protected;METRICS_DISABLEDoption - π³ ~15 MB Docker image β multi-stage build (Go 1.25 / Alpine 3.21)
docker run -p 80:80 andreaskasper/http-honeypotOr with docker-compose (recommended):
cp .env.example .env
# edit .env with your values
docker-compose up -d| Variable | Default | Description |
|---|---|---|
NAME |
(empty) | Instance name β included in all notifications |
HONEYPOT_PORT |
80 |
Host port (docker-compose only) |
| Tar-pit | ||
TAR_PIT_MAX_SEC |
20 |
Max random delay per request in seconds (0 = disabled) |
| Rate limiting | ||
RATE_LIMIT_PER_MIN |
1000 |
Max requests per IP per minute |
| Logging | ||
LOG_DISABLED |
false |
Disable all file logging (notifications still fire) |
LOG_MAX_SIZE_MB |
100 |
Rotate log file when it exceeds this size in MB |
| Pushover | ||
PUSHOVER_APP |
(empty) | Pushover application token |
PUSHOVER_RECIPIENT |
(empty) | Pushover user/group key |
PUSHOVER_NOTIFY_COUNTRY |
(empty) | ISO 3166-1 alpha-2 country code for mobile alert (throttled 1/hour) |
| Webhook (attack events) | ||
WEBHOOK_URL |
(empty) | HTTP POST endpoint for JSON attack events |
WEBHOOK_SECRET |
(empty) | Sent in X-Honeypot-Secret header for receiver verification |
WEBHOOK_URL_RATE_LIMIT_SEC |
(empty) | Optional: Rate limit per IP (seconds between calls) |
| Webhook (unknown URLs) | ||
WEBHOOK_NEW_URL |
(empty) | HTTP POST endpoint for unknown/new URLs (synchronous) |
WEBHOOK_NEW_URL_SECRET |
(empty) | Sent in X-Honeypot-Secret header for receiver verification |
WEBHOOK_NEW_URL_CACHE_SEC |
60 |
Cache responses for identical paths (seconds) |
WEBHOOK_NEW_URL_TIMEOUT_SEC |
5 |
Timeout for webhook call (seconds) |
DEFAULT_REDIRECT |
false |
Redirect to / instead of 404 when webhook doesn't respond |
| Prometheus metrics | ||
METRICS_USER |
admin |
Username for /metrics Basic Auth |
METRICS_PASSWORD |
password |
Password for /metrics Basic Auth |
METRICS_REALM |
Prometheus Server |
HTTP Basic Auth realm |
METRICS_DISABLED |
false |
Disable the /metrics endpoint entirely |
| AbuseIPDB | ||
ABUSEIPDB_KEY |
(empty) | AbuseIPDB API key β leave empty to disable |
ABUSEIPDB_SLEEP |
86400 |
Cooldown in seconds before reporting the same IP again (default: 24 h) |
The honeypot can call a webhook for unknown/new URLs (paths that don't match any attack trap) and serve custom responses. This enables:
- Implementing custom attack vectors dynamically
- A/B testing different response strategies
- Creating adaptive honeypot behavior
- Analyzing new attack patterns before hardcoding traps
The webhook receives comprehensive request details:
{
"server": "my-honeypot",
"timestamp": "2026-02-19T10:00:00Z",
"ip": "1.2.3.4",
"method": "GET",
"host": "example.com",
"path": "/custom/path",
"query_string": "id=123&debug=true",
"query_params": {"id": "123", "debug": "true"},
"headers": {
"User-Agent": "Mozilla/5.0...",
"Accept": "text/html",
"X-Forwarded-For": "1.2.3.4"
},
"cookies": {"session": "abc123"},
"user_agent": "Mozilla/5.0...",
"content_type": "application/json",
"remote_addr": "1.2.3.4:54321",
"request_uri": "/custom/path?id=123",
"proto": "HTTP/1.1",
"tls": false,
"api_key_used": "",
"post_body": "{\"data\":\"test\"}",
"content_length": 15,
"ipinfo": {"country": "DE", "city": "Berlin", "org": "AS3320"}
}The webhook can return custom responses in two ways:
1. JSON Response (structured):
{
"status": 200,
"body": "<html><body>Custom content</body></html>",
"content_type": "text/html; charset=utf-8",
"headers": {
"X-Custom-Header": "value",
"Cache-Control": "no-cache"
}
}2. Plain Text/HTML Response: Return raw HTML or text directly (not JSON). The content-type will be auto-detected.
Redirect Shorthand:
{
"status": 301,
"redirect": "/moved-here"
}Automatically sets the Location header.
Response Caching:
Responses are cached by METHOD:PATH for WEBHOOK_NEW_URL_CACHE_SEC seconds (default: 60s). This prevents repeated webhook calls for the same URL pattern.
Fallback Behavior:
- If webhook is empty or returns no custom response β 404 (or 301 to
/ifDEFAULT_REDIRECT=true) - If webhook times out or errors β 404 (or 301 to
/)
The /metrics endpoint includes:
webhook_new_url_callsβ Total webhook callswebhook_new_url_timeout_msβ Cumulative response timewebhook_new_url_cache_hitsβ Cache hitswebhook_new_url_cache_missβ Cache misseswebhook_new_url_custom_responsesβ Custom responses served
Every fake response that contains credentials embeds an IP-specific honeytoken β a fake API key with a hp_live_ prefix, derived from md5(ip + trap_name).
Tokens appear in:
/actuator/envβAWS_SECRET_ACCESS_KEY/.envβSTRIPE_SECRET_KEY/.env.local,/.env.bak,/.env.productionand friends βSTRIPE_SECRET_KEY/.aws/credentialsβaws_secret_access_key/.git-credentialsβ the password in the fake clone URL/.netrc,/_netrc,/.pgpassβpassword/.npmrc,/.pypirc,/.s3cfgβ_authToken/.docker/config.jsonβauths[].identitytoken/@fs/*(Vite, CVE-2025-30208) βSTRIPE_SECRET_KEY/api/v*/users/{id}βapi_keyfield/api/v1/api_key(Langflow) βapi_keys[].api_key/api/v1/auto_login(Langflow, CVE-2026-9198) βaccess_token/api/session/properties(Metabase) βsetup-token/api/database(Metabase) βdata[].details.password/p/u/doAuthentication.do(CitrixBleed 2) β fake leaked memory in<InitialValue>/global-protect/getconfig.esp(PAN-OS) β<portal-userauthcookie>/rest/com/vmware/cis/session(vCenter) β the session id invalue/.claude/mcp.jsonand friends βenv.GITHUB_PERSONAL_ACCESS_TOKEN/.claude/.credentials.jsonβclaudeAiOauth.accessToken/api/auth/authenticate(N-central) βtokens.access.token
If an attacker submits a token back to any endpoint (as a header, cookie, query parameter, or POST body), the honeypot:
- Detects it in
detectHoneytokenInRequest() - Sets
attack_tag = "honeytoken-used"andis_honeytoken_use = true - Fires a
honeytoken_usedwebhook event (separate from normalattackevents) - Increments the
http_honeytokens_usedPrometheus counter - Reports to AbuseIPDB
This means you get alerted when a credential stolen from your honeypot is actually used β even from a completely different IP, indicating sharing or resale.
When ABUSEIPDB_KEY is set, every attack triggers an async report to AbuseIPDB:
- Category 21 (Web App Attack) for most traps
- Category 14 + 21 (Port Scan + Web App Attack) for scanner-style traps (any
attack_tagcontainingscan, pluscgi-scan) - Cooldown: the same IP is not reported more than once per
ABUSEIPDB_SLEEPseconds (default: 24 h) - Fully async β never blocks the response
- Non-fatal β errors are logged but don't affect honeypot operation
Report comment format:
HTTP honeypot [my-honeypot]: spring-actuator-env | GET /actuator/env | UA: python-requests/2.31.0
{
"event": "attack",
"server": "my-honeypot",
"timestamp": "2025-02-12T14:32:00Z",
"ip": "1.2.3.4",
"method": "GET",
"host": "example.com",
"path": "/actuator/env",
"user_agent": "python-requests/2.31.0",
"is_attack": true,
"attack_tag": "spring-actuator-env",
"api_key_used": "",
"is_honeytoken_use": false,
"ipinfo": { "country": "CN", "city": "Beijing", "org": "AS4134" }
}For honeytoken reuse events, event is "honeytoken_used" and is_honeytoken_use is true. Route these with highest priority in your n8n/Slack flows.
| Category | Tags |
|---|---|
| Spring Boot Actuator | spring-actuator-health/env/beans/heapdump/shutdown |
| WordPress | wp-login, wp-admin, xmlrpc, wp-wlwmanifest, wordpress-scan |
| Joomla | joomla-admin |
| phpMyAdmin | phpmyadmin-index, phpmyadmin-setup |
| Apache Tomcat | tomcat-manager |
| Apache Solr | apache-solr |
| Jenkins | jenkins-script, jenkins-api |
| H2 / JBoss | h2-console |
| Microsoft Exchange | owa-login, exchange-ews, exchange-proxylogon, exchange-ecp, owa-xjs |
| Microsoft SharePoint | sharepoint-toolpane, sharepoint-scan |
| Adobe ColdFusion | coldfusion-admin, coldfusion-scan |
| Fortinet / VPN | fortinet-fgt, sonicwall-vpn, pulse-secure, cisco-asa-vpn |
| Citrix NetScaler π― | citrix-netscaler-bleed, citrix-netscaler-logon, citrix-netscaler-scan |
| PAN-OS GlobalProtect π― | panos-globalprotect-login, panos-globalprotect-prelogin, panos-globalprotect-config, panos-globalprotect-scan |
| Kemp LoadMaster | loadmaster-api |
| N-able N-central π― | nable-ncentral-auth, nable-ncentral-soap, nable-ncentral-scan |
| VMware vCenter π― | vmware-vcenter-sdk, vmware-vcenter-session, vmware-vcenter-websso, vmware-vcenter-scan |
| Kubernetes | k8s-pods, k8s-secrets |
| Docker API | docker-api |
| Grafana | grafana |
| Metabase π― | metabase-properties, metabase-sqli, metabase-setup-validate, metabase-database-list, metabase-scan |
| Confluence | confluence-rce |
| Liferay | liferay-rce |
| PHP | phpunit-rce, phpinfo |
| Apache | apache-server-status |
| Routers / legacy | fritzbox, admin-config, bag2, config-getuser |
| Cloud Metadata | aws-metadata, gcp-metadata, do-metadata |
| AI / LLM tooling π― | langflow-rce, langflow-autologin, langflow-apikey, langflow-scan |
| AI agents / MCP π― | mcp-server-probe, ai-assistant-config, ai-assistant-credentials, llm-openai-models, ollama-tags, ssrf-metadata-probe |
| REST API IDOR π― | rest-api-idor-users/accounts/admin/customers/employees |
| Credential leaks π― | env-file, env-file-variant, aws-credentials, htpasswd, ssh-key |
| Developer credential stores π― | git-credentials, password-store-leak, registry-token-leak |
| Vite dev server π― | vite-file-read |
| Git leaks | git-config, git-head |
| Config leaks | spring-config-leak, docker-compose-leak |
| API specs | swagger |
| Backup files | backup-file |
| Webshells | webshell |
| Path traversal | path-traversal-passwd |
| Log4Shell | log4shell |
| CGI scanning | cgi-scan |
| Honeytokens π― | honeytoken-used |
π― = embeds honeytoken in response